#ifndef CUSTOMGRAPHICSSCENE_H
#define CUSTOMGRAPHICSSCENE_H

#include <QGraphicsScene>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>

class Shape;
class Flow;
class SceneTool;
class SelectionSceneTool;
class FlowSceneTool;
class ShapeSceneTool;

/**
 * @class CustomGraphicsScene
 * Этот класс отвечает за все, связанное с рабочим полем:
 * за создание/удаление фигур, за управление состоянием фигур (т.е. контролем отмен),
 * за работу с мышью (создание/изменение фигур) - правда, делегирует это вспомогательным
 * структурам, за копирование выделенных фигур, за вставку фигур, и т.п.
 * В общем, он несет всю ответственность за работу с диаграммой как единым целым.
 *
 * @see SceneTool
 * @see Shape
 */
class CustomGraphicsScene : public QGraphicsScene
{
    Q_OBJECT
	friend class SceneTool; // могу я хоть раз себе позволить?..
public:
	/// Загружает сцену из XML
	static CustomGraphicsScene *fromXML (const QString &xml, CustomGraphicsScene *scene);
	/// Возвращает сцену, преобразованную в XML-формат
	QString toXML();

public:
	enum EditorTool {
		SELECTION	= 0,
		ARROWFLOW	= 1,
		NOTEFLOW	= 2,
		ACTION		= 3,
		INITIAL		= 4,
		FINAL		= 5,
		DECISION	= 6,
		NOTE		= 7
	};

	CustomGraphicsScene(QObject *parent = 0);
	~CustomGraphicsScene();

	/** @deprecated см. setSceneTool() */
	void setTool (EditorTool t);
	/** @deprecated см. sceneTool() */
	EditorTool tool() const;

	bool setSceneTool (SceneTool *tool);
	SceneTool *sceneTool() const;

	QList<Shape *> shapes() const;
	void addShape (Shape *shape);
	void removeShape (Shape *shape);
	Shape *takeShape (Shape *shape);
	void removeAllShapes();
	void removeSelectedShapes();
	CustomGraphicsScene *cutSelectedShapes();
	void adjustFlowsAndTempShapesSelection();
	QList<Shape *> selectedShapes();

	QList<Shape *> addOtherSceneItems (CustomGraphicsScene *other);
	CustomGraphicsScene *extractSelectionCopy();

signals:
	/**
	 * Испускается, когда состояние сцены изменяется пользователем.
	 * Используется для реализации многоуровневой отмены (сама сцена
	 * отмену не реализует, она лишь предоставляет средства для этого).
	 */
	void stateChangedByUser();

public slots:
	/**
	 * Предполагается, что этот слот будет активироваться извне, чтобы
	 * уведомить сцену о том, что ее состояние изменилось (например, при
	 * вставке фигур пользователем - лучше сделать это вручную, т.к., формально,
	 * сцена не должна знать, что эта операция видна пользователю, а не для
	 * каких-то служебных целей была проведена).
	 */
	void notifyStateChangeByUser();

protected:
	void mousePressEvent (QGraphicsSceneMouseEvent *event);
	void mouseMoveEvent (QGraphicsSceneMouseEvent *event);
	void mouseReleaseEvent (QGraphicsSceneMouseEvent *event);
	void mouseDoubleClickEvent (QGraphicsSceneMouseEvent *event);

private:
	SelectionSceneTool *selection_tool;
	FlowSceneTool *arrowflow_tool;
	FlowSceneTool *noteflow_tool;
	ShapeSceneTool *action_tool;
	ShapeSceneTool *decision_tool;
	ShapeSceneTool *initialnode_tool;
	ShapeSceneTool *finalnode_tool;
	ShapeSceneTool *note_tool;
	EditorTool _tool;
	SceneTool *_currentTool;
	QList<Shape *> _shapes;

signals:
	/** Если изменяется инструмент, с которым работает сцена */
	void toolChanged();
};

#endif // CUSTOMGRAPHICSSCENE_H
